﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlClient;
using System.Linq;
using Rendiciones.Logica.Enumeradores;
using Rendiciones.Logica.Modelos;
using Tesla.Excepciones;
using Tesla.Proveedores;
using Tesla.Validador;
using System.Globalization;

namespace Rendiciones.Logica.Servicios
{
    internal class ServProyecto : IServProyecto
    {
        private readonly IProveedor _proveedor;
        private readonly IValidador _validador;

        public ServProyecto(IProveedor proveedor, IValidador validador)
        {
            _proveedor = proveedor;
            _validador = validador;
        }

        public Proyecto Leer(int idProyecto)
        {
            try
            {
                var proyecto = _proveedor.Read(new Proyecto { IdProyecto = idProyecto });
                proyecto.Custodios = CargarCustodios(idProyecto);
                return proyecto;
            }
            catch (NoHuboResultadosException)
            {
                return null;
            }
        }

        private List<Usuario> CargarCustodios(int idProyecto)
        {
            try
            {
                var usuarios = _proveedor.Search(new Usuario(), new { IdProyecto = idProyecto }, apellido:"Custodios").ToList();
                return usuarios;
            }
            catch (NoHuboResultadosException)
            {
                return new List<Usuario>();
            }
        }

        public List<Proyecto> Buscar(string prefix, bool soloActivos)
        {
            try
            {
                var usuarios = _proveedor.Search(new Proyecto(), new { Prefix = prefix, SoloActivos = soloActivos }, apellido: "Mantenedor").ToList();
                return usuarios;
            }
            catch (NoHuboResultadosException)
            {
                return new List<Proyecto>();
            }
        }

        public void Guardar(ref Proyecto proyecto)
        {
            Validar(proyecto);
            EliminarRoles(proyecto);
            if (proyecto.IdProyecto.Equals(0))
                _proveedor.Create(ref proyecto);
            else
                _proveedor.Update<Proyecto>(proyecto);
            GrabarRoles(proyecto);
        }

        private void EliminarRoles(Proyecto proyecto)
        {
            _proveedor.Delete<Usuario>(new Usuario(), new { proyecto.IdProyecto }, apellido: "Roles");
        }

        private void GrabarRoles(Proyecto proyecto)
        {
            var usr = new Usuario();
            usr.IdUsuario = proyecto.IdGerente;
            _proveedor.Create(ref usr, new { proyecto.IdProyecto, IdRol = 3 }, apellido: "Rol");
            usr.IdUsuario = proyecto.IdAdministrador;
            _proveedor.Create(ref usr, new { proyecto.IdProyecto, IdRol = 2 }, apellido: "Rol");
            foreach (var custodio in proyecto.Custodios)
            {
                var usuario = custodio;
                _proveedor.Create(ref usuario, new { proyecto.IdProyecto, IdRol = 1 }, apellido: "Rol");
            }
        }

        public void Desactivar(Proyecto proyecto)
        {
            _proveedor.Delete<Proyecto>(proyecto);
        }

        private void Validar(Proyecto proyecto)
        {
            var mensajesDeValidacion = _validador.Valida(proyecto, new Dictionary<string, object>()).ToList();
            if (!string.IsNullOrEmpty(proyecto.Nombre))
            {
                var proyectos = Buscar("", false).Where(p => !p.IdProyecto.Equals(proyecto.IdProyecto));
                if (proyectos.Any(p => p.Nombre.ToLower().Equals(proyecto.Nombre.ToLower())))
                    mensajesDeValidacion.Add(new MensajeDeValidacion { Mensaje = "El nombre del proyecto ya se encuentra ingresado", NombreCampo = "Nombre" });
            }
            if (!proyecto.IdGerente.Equals(0) && !proyecto.IdAdministrador.Equals(0))
            {
                if (proyecto.IdGerente.Equals(proyecto.IdAdministrador))
                {
                    mensajesDeValidacion.Add(new MensajeDeValidacion { Mensaje = "No se puede ingresar al mismo usuario como Gerente y Administrador en un mismo proyecto", NombreCampo = "IdGerente" });
                    mensajesDeValidacion.Add(new MensajeDeValidacion { Mensaje = "No se puede ingresar al mismo usuario como Gerente y Administrador en un mismo proyecto", NombreCampo = "IdAdministrador" });
                }
            }
            if (!proyecto.IdGerente.Equals(0))
            {
                if(proyecto.Custodios.Any(c => c.IdUsuario.Equals(proyecto.IdGerente)))
                    mensajesDeValidacion.Add(new MensajeDeValidacion { Mensaje = "No se puede ingresar al mismo usuario como Gerente y Custodio en un mismo proyecto", NombreCampo = "IdGerente" });
            }
            if (!proyecto.IdAdministrador.Equals(0))
            {
                if (proyecto.Custodios.Any(c => c.IdUsuario.Equals(proyecto.IdAdministrador)))
                    mensajesDeValidacion.Add(new MensajeDeValidacion { Mensaje = "No se puede ingresar al mismo usuario como Administrador y Custodio en un mismo proyecto", NombreCampo = "IdAdministrador" });
            }
            if (mensajesDeValidacion.Any(m => !string.IsNullOrEmpty(m.Mensaje)))
                throw new ResultadoValidacionException("Hay campos incompletos o que deben ser modificados", mensajesDeValidacion);
        }

        public List<Proyecto> ActivosDondeSoy(int idUsuario, ERol rol)
        {
            try
            {
                var proyectos = _proveedor.Search(new Proyecto(), new { @IdUsuario = idUsuario, @RolUsuario = (int)rol }, apellido: "PorUsuario").ToList();
                return proyectos;
            }
            catch(NoHuboResultadosException)
            {
                return new List<Proyecto>();
            }
        }
    }

    public interface IServProyecto
    {
        Proyecto Leer(int idProyecto);
        List<Proyecto> Buscar(string prefix, bool soloActivos);
        void Guardar(ref Proyecto proyecto);
        void Desactivar(Proyecto proyecto);
        List<Proyecto> ActivosDondeSoy(int idUsuario, ERol rol);
    }
}